package com.sunl.mall.trace.web;

import com.sunl.mall.trace.util.SerialNo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class TraceClientInterceptor implements AsyncHandlerInterceptor {
    private static final Logger log = LoggerFactory.getLogger(TraceClientInterceptor.class);
    /**
     * 日志等级
     * <p>
     * 1打印url
     * 2打印url和参数
     */
    public static int logLevel;
    private final static String traceIdKey = "initiationId";

    public TraceClientInterceptor() {
        TraceClientInterceptor.logLevel = getProp("trace.logLevel", 1);
    }

    public TraceClientInterceptor(int logLevel) {
        TraceClientInterceptor.logLevel = logLevel;
    }

    // Controller方法处理之前
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (handler instanceof HandlerMethod) {
            MDC.put(traceIdKey, SerialNo.init());
        }
        if (logLevel == 1) {
            log.info("Start to handle request. url:[{}]", request.getRequestURI());
        } else if (logLevel == 2) {
            log.info("start to handle request. url:[{}] params:[{}]", request.getRequestURI(), this.mapToString(request.getParameterMap()));
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    // DispatcherServlet进行视图的渲染之后
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        if (handler instanceof HandlerMethod) {
            MDC.remove(traceIdKey);
            SerialNo.clear();
        }
    }

    private String mapToString(Map<String, String[]> paramMap) {
        StringBuilder stringBuilder = new StringBuilder(500);
        Set<Map.Entry<String, String[]>> entrySet = paramMap.entrySet();
        for (Iterator<Map.Entry<String, String[]>> itr = entrySet.iterator(); itr.hasNext(); stringBuilder.append("],")) {
            Map.Entry<String, String[]> entry = itr.next();
            stringBuilder.append(entry.getKey());
            stringBuilder.append("=[");
            String[] values = entry.getValue();
            int len;
            if ((len = values.length) > 0) {
                int i = 0;
                while (i < len) {
                    stringBuilder.append(values[i]);
                    ++i;
                    if (i < len) {
                        stringBuilder.append(",");
                    }
                }
            }
        }
        return stringBuilder.toString();
    }

    private static int getProp(String key, int defaultVal) {
        String property = System.getProperty(key);
        if (property != null) {
            try {
                return Integer.parseInt(property);
            } catch (Exception ignore) {
            }
        }

        return defaultVal;
    }

    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {

    }
}
